#include "control.h"

#define MAX_CONTROL_CMD_FN  90

INT8U CtrProcGroupFun(INT16U pn, INT8U fn, INT8U *ptr, INT16U* pSize);
INT8U CtrProcPnCmd(INT16U pn, LCDataUnitIDDataType* pDataUnitIDData, INT8U *pData, INT16U* pSize);
INT8U CtrProcOneDUID(LCDataUnitIDDataType* pDataUnitIDData, INT16U *pSize);

void CtrInit(void)
{
    INT8U buff[4];

    if (FSRead(AFN05_STATE_DATA_FD, 0, buff, 1) == 0)
    {
        FSCreateFile(AFN05_STATE_DATA_FD, 1024 * 4);
    }
}

void CtrReadArgState(AFN05ArgStateDataType *buff)
{
    FSRead(AFN05_STATE_DATA_FD, 0, (INT8U*)buff, sizeof(AFN05ArgStateDataType));
}
void CtrWriteArgState(AFN05ArgStateDataType * data)
{
    FSWrite(AFN05_STATE_DATA_FD, 0, (INT8U*)data, sizeof(AFN05ArgStateDataType));
}

void CtrProcCmd(GdSuperFrameType * pLCSuperFrame)
{
    LCFrameType *pLCFrame = &(pLCSuperFrame->frame);
    INT8U *ptr, ret;
    INT16U duLen, size;

    duLen = pLCFrame->len.len_un.len_s.m_len - LC_DATA_EXT_LEN;
    if (pLCFrame->userdata.appseq.tpv == 1)
    {
        duLen -= sizeof(LCTPType);
        if (MasterCheckTp((LCTPType*)(pLCFrame->userdata.data + duLen)) == FALSE)
        {
            MasterSendAllNACKFrame(pLCSuperFrame);
            return;
        }
    }
    duLen -= 16;                          // pw

    if (duLen == 0)
    {
        MasterSendAllNACKFrame(pLCSuperFrame);
    }

    ptr = (INT8U*)(pLCFrame->userdata.data);

    while (duLen > 3)
    {
        ret = CtrProcOneDUID((LCDataUnitIDDataType*)ptr, &size);
        if (ret == LC_NO_ERR)
        {
            if (duLen >= size)
            {
                ptr += size;
                duLen -= size;
            }
            else
            {
                break;
            }
        }
        else
        {
            MasterSendAllNACKFrame(pLCSuperFrame);
            return;
        }
    }

    MasterSendAllACKFrame(pLCSuperFrame);

    return;
}

INT8U CtrProcOneDUID(LCDataUnitIDDataType * pDataUnitIDData, INT16U * pSize)
{
    INT8U *pData;
    INT8U ucGroup, ucPoint, da1, da2, ret;
    INT16U size;

    *pSize = sizeof(LCDataUnitIDType);
    pData = (INT8U*)(pDataUnitIDData->data);
    if (pDataUnitIDData->da.da1 == 0 || pDataUnitIDData->da.da2 == 0)
    {
        ret = CtrProcPnCmd(0, pDataUnitIDData, pData, &size);
        *pSize += size;
        return ret;
    }
    else if (pDataUnitIDData->da.da1 == 0xff && pDataUnitIDData->da.da2 == 0xff)
    {
        return LC_ERR_DATA;
    }
    else
    {
        da2 = pDataUnitIDData->da.da2;
        da1 = pDataUnitIDData->da.da1;
        for (ucGroup = 0; ucGroup < 8; ucGroup++)
        {
            if (da2 & BitsPattern[ucGroup])
            {
                for (ucPoint = 0; ucPoint < 8; ucPoint++)
                {
                    if (da1 & BitsPattern[ucPoint])
                    {
                        // from p1 to p64
                        ret = CtrProcPnCmd(ucGroup * 8 + ucPoint + 1, pDataUnitIDData, pData, &size);
                        if (ret == LC_NO_ERR)
                        {
                            *pSize += size;
                            pData += size;
                        }
                        else
                        {
                            return ret;
                        }
                    }
                }
            }
        }
    }
    return LC_NO_ERR;
}

INT8U CtrProcPnCmd(INT16U pn, LCDataUnitIDDataType * pDataUnitIDData, INT8U * pData, INT16U * pSize)
{
    INT8U ucNum;
    INT16U size;
    INT8U fn;
    LCDTType* pDT;
    INT8U *ptr;
    INT8U ret;

    pDT = &(pDataUnitIDData->dt);
    ptr = pData;
    *pSize = 0;
    for (ucNum = 0; ucNum < 8; ucNum++)
    {
        if (pDT->dt1 & BitsPattern[ucNum])
        {
            fn = pDT->dt2 * 8 + ucNum + 1;

            size = 0;

            if (fn == 0 && fn > MAX_CONTROL_CMD_FN)
            {
                return LC_ERR_DATA;
            }
            ret = CtrProcGroupFun(pn, fn, ptr, &size);
            if ( ret != LC_NO_ERR)
            {
                return ret;
            }

            ptr += size;
            *pSize += size;
        }
    }
    return LC_NO_ERR;
}

void CtrDelPortAllMeter(INT8U port)
{
    INT16U devNo;
    MeterACSampleType mpArg;

    for (devNo = 1; devNo <= TM_MP_NUM; devNo++)
    {
        ArgGetTmArgFn10(devNo, &mpArg);

        if (mpArg.port.portNo == port &&
            mpArg.mp != 0 &&
            mpArg.mp <= TM_MP_NUM)
        {
            mpArg.mp = 0;
            ArgSetTmArgFn10(devNo, &mpArg);
        }
    }
}

INT8U CtrProcGroupFun(INT16U pn, INT8U fn, INT8U* ptr, INT16U* pSize)
{
    INT32U seconds;
    DateTimeType dateTime = { 0, 0, 0, 0, 0 };
    LCDataFormat01Type *pDateTime;
    DateTimeType tmTime1, tmTime2;
    ERC41DataType ERC41Data;

    *pSize = 0;
    switch (fn)
    {
    case FN29:
    {
        AFN05ArgStateDataType argState;
        CtrReadArgState(&argState);
        argState.fn29Arg = 0xAA;
        CtrWriteArgState(&argState);
        break;
    }
    case FN30:
    {
        AFN05ArgStateDataType argState;
        CtrReadArgState(&argState);
        argState.fn30Arg = *ptr;
        CtrWriteArgState(&argState);
        gCtrParaChg = 1;
        break;
    }
    case FN31:
        pDateTime = (LCDataFormat01Type*)ptr;
        dateTime.second = CmnBcd2Byte(pDateTime->second);
        dateTime.minute = CmnBcd2Byte(pDateTime->minute);
        dateTime.hour = CmnBcd2Byte(pDateTime->hour);
        dateTime.day = CmnBcd2Byte(pDateTime->day);
        dateTime.month = CmnBcd2Byte(pDateTime->month);
        dateTime.year = CmnBcd2Byte(pDateTime->year);
        seconds = RtcDateTimeToSecond(dateTime);

        tmTime1 = RtcSecondToDataTime(RtcGetTime());
        RtcSetTime(seconds);
        *pSize = sizeof(LCDataFormat01Type);

        tmTime2 = RtcSecondToDataTime(RtcGetTime());

        DateTimeToFmt1(tmTime1, &ERC41Data.startTime);
        DateTimeToFmt1(tmTime2, &ERC41Data.endTime);
        ERC41Data.pnFlag.pn = 0;
        ERC41Make(seconds, 0, &ERC41Data);

        break;
    case FN37:
    {
        AFN05ArgStateDataType argState;
        CtrReadArgState(&argState);
        argState.fn29Arg = 0xFF;
        CtrWriteArgState(&argState);
        break;
    }
    case FN38:
        LinkSetRelogin();
        break;
    case FN39:
        if (gLinkInfor.vpnMode.onlineType == VPN_MODE_SLEEP ||
            gLinkInfor.vpnMode.onlineType == VPN_MODE_SLEEP_TIME)
        {
            LinkSetLogout();
        }
        else
        {
            LinkSetReload(FN39);
        }
        break;
    case FN49:
    case FN50:
    case FN51:
#if (JIANGSU_ADD_BY_ZHF)
        {
            INT8U port;

            port = *ptr;
            if (port < 2 || port > 4)
            {
                return LC_ERR_DATA;
            }
            gAssignSMPsample = port;
            break;
        }
#endif
    case FN52:
        break;
    case FN53:
        CtrDelPortAllMeter(ptr[0]);
        *pSize = 1;
        break;
    case FN57:
    {
        INT8U i, num = ptr[0];

        if (num == 0)
        {
            ERCDelErc(0);
        }
        else
        {
            for (i = 0; i < num; i++)
            {
                ERCDelErc(ptr[1 + i]);
            }
        }

        *pSize = num + 1;
        break;
    }
    case FN90:
        ERC60MakeEx(*(INT32U*)ptr);
        *pSize = 4;
        break;

    case FN149:
    {
        AFN05ArgStateDataType argState;
        CtrReadArgState(&argState);
        argState.fn149Arg = ptr[0];
        CtrWriteArgState(&argState);

        *pSize = 1;
        break;
    }

    case FN150:
        ArgResetMpStateFlag();
        break;
    default:
        return LC_ERR_DATA;
    }

    return LC_NO_ERR;
}

